package com.lin.operatorlogrecord.content;


import com.lin.operatorlogrecord.exception.OperatorLogException;

import java.lang.reflect.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ln cheng hao
 */
public class ObjectUpdateLogUtil {


    /**
     * 生成变更记录
     * @return 变更记录
     */
    public List<String> generatorChangeLog(Object oldObject,Class<?> oldClazz,Object newObject,Class<?> newClazz,String objectType) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        if (Objects.isNull(oldObject) || Objects.isNull(newObject)){
            throw new OperatorLogException("对比对象不能为null");
        }
        // 封装对象
        OperatorLogMetaDataBuilder builder = new OperatorLogMetaDataBuilder();
        OperatorLogMetaData oldOperatorLogMetaData = builder.getChangeModel(oldObject, oldClazz);
        OperatorLogMetaData newOperatorLogMetaData = builder.getChangeModel(newObject, newClazz);
        return generatorChangeLog(oldOperatorLogMetaData, newOperatorLogMetaData,objectType);
    }

    /**
     * 生成变更记录
     * @return 变更记录
     */
    public List<String> generatorChangeLog(OperatorLogMetaData oldOperatorLogMetaData, OperatorLogMetaData newOperatorLogMetaData, String objectType)  {
        List<String> result = new ArrayList<>();
        // 父类字段变更和引用子对象
        String filedChangeLog = getFiledChangeLog(oldOperatorLogMetaData.getFieldMap(), newOperatorLogMetaData.getFieldMap(),
                oldOperatorLogMetaData.getSubObjectMap(), newOperatorLogMetaData.getSubObjectMap(), oldOperatorLogMetaData.getFiledNameAndPriorityMap(), oldOperatorLogMetaData.getName(), objectType);
        if (isNoBlankString(filedChangeLog)){
            result.add(filedChangeLog);
        }
        // 复杂列表变更
        result.addAll(getComplexListChangeLogs(oldOperatorLogMetaData.getListMap(), newOperatorLogMetaData.getListMap()));
        return result;
    }



    /**
     * 获取父类字段变更和引用子对象字段变更
     */
    private String getFiledChangeLog(Map<String,String> oldFieldMap, Map<String,String> newFieldMap,
                                     Map<String, OperatorLogMetaData> oldQuoteSubObject, Map<String, OperatorLogMetaData> newQuoteSubObject,
                                     Map<String,Integer> filedNameAndPriorityMap, String objectName, String objectType){
        List<OperatorLogRecord> result = new ArrayList<>();
        // 父类字段变更
        if (Objects.nonNull(oldFieldMap) && Objects.nonNull(newFieldMap)){
            for (Map.Entry<String,String> entry : oldFieldMap.entrySet()){
                String newValue = newFieldMap.get(entry.getKey());
                if (Objects.nonNull(newValue) && !newValue.equals(entry.getValue())){
                    result.add(new OperatorLogRecord(filedNameAndPriorityMap.get(entry.getKey()),OperatorLogContentUtil.updateFiledFormat(entry.getValue(), newValue, entry.getKey())));
                }
            }
        }
        // 引用字段变更
        if (Objects.nonNull(oldQuoteSubObject) && Objects.nonNull(newQuoteSubObject)){
            for (Map.Entry<String, OperatorLogMetaData> entry : oldQuoteSubObject.entrySet()){
                OperatorLogMetaData newValue = newQuoteSubObject.get(entry.getKey());
                if (Objects.nonNull(newValue) && !newValue.getId().equals(entry.getValue().getId())){
                    result.add(new OperatorLogRecord(filedNameAndPriorityMap.get(entry.getKey()),OperatorLogContentUtil.updateFiledFormat(entry.getValue().getName(), newValue.getName(), entry.getKey())));
                }
            }
        }

        if (!result.isEmpty()){
            // 根据优先级排序
            result.sort(java.util.Comparator.comparingInt(OperatorLogRecord::getPriority));
            return OperatorLogContentUtil.updateFormat(objectType, objectName) + result.stream().map(OperatorLogRecord::getChangeLogContent).collect(Collectors.joining());
        }
        return null;
    }


    /**
     * 获取复杂列表变更
     */
    private List<String> getComplexListChangeLogs(Map<String,List<OperatorLogMetaData>> oldListMap, Map<String,List<OperatorLogMetaData>> newListMap){
        List<String> result = new ArrayList<>();
        if (Objects.isNull(oldListMap) || Objects.isNull(newListMap)){
            return result;
        }
        for (Map.Entry<String,List<OperatorLogMetaData>> entry : oldListMap.entrySet()){
            List<OperatorLogMetaData> newOperatorLogMetaData = newListMap.get(entry.getKey());
            if (Objects.nonNull(newOperatorLogMetaData)){
                result.addAll(getComplexListChangeLog(entry.getValue(), newOperatorLogMetaData,entry.getKey()));
            }
        }
        return result;
    }

    /**
     * 获取复杂列表变更
     */
    private List<String> getComplexListChangeLog(List<OperatorLogMetaData> oldOperatorLogMetaDatas, List<OperatorLogMetaData> newOperatorLogMetaDatas, String objectType){
        List<String> result = new ArrayList<>();
        if (Objects.isNull(oldOperatorLogMetaDatas) || Objects.isNull(newOperatorLogMetaDatas)){
            return result;
        }
        // 新增
        List<String> addObjectNames = newOperatorLogMetaDatas.stream().filter(i -> oldOperatorLogMetaDatas.stream()
                .noneMatch(j -> j.getId().equals(i.getId()))).map(OperatorLogMetaData::getName).collect(Collectors.toList());
        if (isNoBlankList(addObjectNames)){
            result.add(OperatorLogContentUtil.addBatchFieldFormat(addObjectNames, objectType));
        }
        // 删除
        List<String> deleteObjectNames = oldOperatorLogMetaDatas.stream().filter(i -> newOperatorLogMetaDatas.stream()
                .noneMatch(j -> j.getId().equals(i.getId()))).map(OperatorLogMetaData::getName).collect(Collectors.toList());
        if (isNoBlankList(deleteObjectNames)){
            result.add(OperatorLogContentUtil.deleteBatchFieldFormat(deleteObjectNames, objectType));
        }
        // 更新
        for (OperatorLogMetaData oldOperatorLogMetaData : oldOperatorLogMetaDatas){
            for (OperatorLogMetaData newOperatorLogMetaData : newOperatorLogMetaDatas){
                if (oldOperatorLogMetaData.getId().equals(newOperatorLogMetaData.getId())){
                    result.addAll(generatorChangeLog(oldOperatorLogMetaData, newOperatorLogMetaData,objectType));
                }
            }
        }
        return result;
    }


    /**
     * 判断字符串是否为null或空字符
     */
    public boolean isNoBlankString(String str){
        return Objects.nonNull(str) && str.length() > 0;
    }

    /**
     * 判断列表是否为null或大小为0
     */
    public boolean isNoBlankList(List<?>  list){
        return Objects.nonNull(list) && !list.isEmpty();
    }

}
